#pragma once

#include <src/data/poly_mod_2.h>
#include <string>

template<typename poly_mod_2> 
void poly_mod_2_example() {
	
  std::cout << std::endl << "----start poly_mod_2_example---------------------" << std::endl ;
  typedef typename poly_mod_2::bitset bitset;
  poly_mod_2 first (std::string("1001"));
  poly_mod_2 second (std::string("0011"));
  poly_mod_2 local1;
  poly_mod_2 local2;

  bool logical = false;

  std::cout << std::endl << "basic operation on bitset" << std::endl ;
  std::cout << std::endl << "first = " << first<< std::endl ;
  std::cout << std::endl << "second = " << second<< std::endl ;

  OS_DYNAMIC_CHECK( !(first==second), "poly_mod_2_example : == failed");
  OS_DYNAMIC_CHECK( (first!=second), "poly_mod_2_example : != failed");


  local1 = first ^ second; local2 = bitset(std::string("1010")); logical = (local1 == local2);
  std::cout << std::endl << " XOR " << local1 << std::endl ;
  OS_DYNAMIC_CHECK( logical, "poly_mod_2_example : XOR failed");

  local1 = first & second; local2 = bitset(std::string("0001")); logical = (local1 == local2);
  std::cout << std::endl << " XAND " << local1<< std::endl ;
  OS_DYNAMIC_CHECK( logical, "poly_mod_2_example : XAND failed");

  local1 = first | second; local2 = bitset(std::string("1011")); logical = (local1 == local2);
  std::cout << std::endl << " OR " << local1 << std::endl ;
  OS_DYNAMIC_CHECK( logical, "poly_mod_2_example : OR failed");

  local1 = first << 2; local2 = bitset(std::string("100100")); logical = (local1 == local2);
  std::cout << std::endl << " SHL " << local1 << std::endl ;
  OS_DYNAMIC_CHECK( logical, "poly_mod_2_example : SHL failed");

  local1 = first >> 2; local2 = bitset(std::string("10")); logical = (local1 == local2);
  std::cout << std::endl << " SHR " << local1 << std::endl ;
  OS_DYNAMIC_CHECK( logical, "poly_mod_2_example : SHR failed");

  std::cout << " assignment ";
  std::cout << std::endl << " NOT " << first<< std::endl ;
  std::cout << (~first) << std::endl;                // 1100 (NOT)
  std::cout << std::endl << " SHL " << first<< std::endl ;
  std::cout << (poly_mod_2)(first<<1) << std::endl;              // 0110 (SHL)
  std::cout << std::endl << " SHR " << first<< std::endl ;
  std::cout << (poly_mod_2) (first>>1) << std::endl;              // 0001 (SHR)

  std::cout << std::endl << "algebraic operations" << std::endl ;

  local1 = first + second; local2 = bitset(std::string("1010")); logical = (local1 == local2);
  std::cout << std::endl << " addition " << local1 << std::endl ;
  OS_DYNAMIC_CHECK( logical, "poly_mod_2_example : addition failed");

  local1 = first*second; local2 = bitset(std::string("11011")); logical = (local1 == local2);
  std::cout << std::endl << " multiplication " << local1 << std::endl ;
  OS_DYNAMIC_CHECK( logical, "poly_mod_2_example : multiplication failed");

  first++; local2 = bitset(std::string("1010")); logical = (first == local2);
  std::cout << std::endl << " incrementation " << local1 << std::endl ;
  OS_DYNAMIC_CHECK( logical, "poly_mod_2_example : incrementation failed");

 //  10100 / 11 : 10100 - 11000 = 1100 - 1100 = 000 - 110 = 00-11 = 0

  local1 = ((first <<= 1) /second); local2 = bitset(std::string("1100")); logical = (local1 == local2);
  std::cout << std::endl << " division " << local1 << std::endl ;
  OS_DYNAMIC_CHECK( logical, "poly_mod_2_example : division failed");
// 10100 = 16+4 = 20 - 1 = 19 = 10011
  --first; local2 = bitset(std::string("10011")); logical = (first == local2);
  std::cout << std::endl << " decrementation " << local1 << std::endl ;
  OS_DYNAMIC_CHECK( logical, "poly_mod_2_example : decrementation failed");

  std::cout << std::endl << "----end poly_mod_2_example---------------------" << std::endl ;
};


void poly_mod_2_test();

